#include "apue.h"
#include <fcntl.h>
#include <sys/uio.h>
#include <sys/socket.h>

#define BUFFSIZE 8192
#define CL_OPEN "open"

int csopen(char*, int);

int
main(int argc, char *argv[])
{
  int n, fd;
  char buf[BUFFSIZE];
  char line[MAXLINE];

  /* read filename to cat from stdin */
  while (fgets(line, MAXLINE, stdin) != NULL) {
    if (line[strlen(line) - 1] == '\n')
      line[strlen(line) - 1] = 0;  /* replace newline with null */
    /* open the file */
    printf("%s open: line= %s\n", __func__, line);
    if ((fd = csopen(line, O_RDONLY)) < 0)
      continue;  /* csopen() prints error from server */

    /* and cat to stdout */
    printf("%s open: fd:%d\n", __func__, fd);
    while ((n = read(fd, buf, BUFFSIZE)) > 0)
      if (write(STDOUT_FILENO, buf, n) != n)
        printf("write error");
    if (n < 0)
      printf("read error");
    close(fd);
  }

  return 0;
}

/*
 * Open th file by sending the "name" and "oflag" to the
 * connection server and reading a file descriptor back.
 */
int
csopen(char *name, int oflag)
{
  pid_t pid;
  int   len;
  char  buf[10];
  struct iovec iov[3];
  static int fd[2] = {-1, -1};

  if (fd[0] < 0) {
    if (socketpair(AF_UNIX, SOCK_STREAM, 0, fd) < 0) {
      err_ret("fd_pipe error");
      return(-1);
    }
    printf("%s fd[0]:%d, fd[1]:%d\n", __func__, fd[0], fd[1]);
    if ((pid = fork()) < 0) {
      err_ret("fork error");
      return(-1);
    } else if (pid == 0) {
      printf("open: start child process\n");
      close(fd[0]);
      if (fd[1] != STDIN_FILENO &&
          dup2(fd[1], STDIN_FILENO) != STDIN_FILENO)
        printf("dup2 error to stdin");
      if (fd[1] != STDOUT_FILENO &&
          dup2(fd[1], STDOUT_FILENO) != STDOUT_FILENO)
        printf("dup2 error to stdout");
      if (execl("../opend/opend", "opend", (char *)0) < 0)
        printf("execl error");
      printf("csopen pid==0 end\n");
    }
    printf("father\n");
    close(fd[1]);
  }
  sprintf(buf, " %d", oflag);
  iov[0].iov_base = CL_OPEN " ";
  iov[0].iov_len = strlen(CL_OPEN) + 1;
  iov[1].iov_base = name;
  iov[1].iov_len = strlen(name);
  iov[2].iov_base = buf;
  iov[2].iov_len = strlen(buf) + 1;
  len = iov[0].iov_len + iov[1].iov_len + iov[2].iov_len;
  if (writev(fd[0], &iov[0], 3) != len) {
    err_ret("writev error");
    return(-1);
  }
  /* read descriptor, returned errors handled by write() */
  return(recv_fd(fd[0], write));
  /* return 0; */
}
